package ooo.reindeer.concurrent;

import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

public class BlockingFileQueue<T> extends FileQueue<T> implements BlockingQueue<T> {

    public BlockingFileQueue(String path, ICoder<T, byte[]> coder) throws Exception {
        this(path, 1024 * 1024 * 16, coder);
    }

    public BlockingFileQueue(String path, int logsize, ICoder<T, byte[]> coder) throws Exception {
        super(path, logsize, coder);
    }

//    @Override
//    public void addFirst(T e) {
//        throw new UnsupportedOperationException("addFirst Unsupported now");
//    }

//    @Override
//    public void addLast(T e) {
//        if (!offerLast(e)) {
//            throw new IllegalStateException("Queue full");
//        }
//
//    }

//    @Override
//    public Iterator<T> descendingIterator() {
//        throw new UnsupportedOperationException("descendingIterator Unsupported now");
//    }

    @Override
    public int drainTo(Collection<? super T> c) {

        return drainTo(c, Integer.MAX_VALUE);
    }

    @Override
    public int drainTo(Collection<? super T> c, int maxElements) {
        T data;
        while (c.size() >= maxElements && (data = super.poll()) != null) {
            c.add(data);
        }
        return c.size();
    }

//    @Override
//    public T getFirst() {
//        throw new UnsupportedOperationException("getFirst Unsupported now");
//
//    }

//    @Override
//    public T getLast() {
//        throw new UnsupportedOperationException("getLast Unsupported now");
//    }

    @Override
    public boolean offer(T bytes, long timeout, TimeUnit unit) throws InterruptedException {
        long fix = 0;
        long timeOut = unit.convert(timeout, TimeUnit.MILLISECONDS);
        while (!offer(bytes))
        {

            if (timeOut - fix <= 0) {
                return offer(bytes);
            } else {
                long begin = System.currentTimeMillis();
                TimeUnit.MILLISECONDS.sleep(100);
                fix += System.currentTimeMillis() - begin;
            }

        }
        return true;
    }

    @Override
    public boolean offer(T bytes) {
        while(!super.offer(bytes)){
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return true;
    }

//    @Override
//    public boolean offerFirst(T bytes) {
//        throw new UnsupportedOperationException("offerFirst Unsupported now");
//    }

//    @Override
//    public boolean offerFirst(T bytes, long timeout, TimeUnit unit) throws InterruptedException {
//        throw new UnsupportedOperationException("offerFirst Unsupported now");
//    }

//    @Override
//    public boolean offerLast(T bytes) {
//        return offer(bytes);
//
//    }

//    @Override
//    public boolean offerLast(T bytes, long timeout, TimeUnit unit) throws InterruptedException {
//        return offer(bytes, timeout, unit);
//    }

//    @Override
//    public T peekFirst() {
//        throw new UnsupportedOperationException("peekFirst Unsupported now");
//    }

//    @Override
//    public T peekLast() {
//        throw new UnsupportedOperationException("peekLast Unsupported now");
//    }

    @Override
    public T poll(long timeout, TimeUnit unit) throws InterruptedException {
        T object;
        int fix = 0;
        long timeOut = TimeUnit.MILLISECONDS.convert(timeout, unit);
        while ((object = this.poll()) == null) {

            if (timeOut - fix <= 0) {
                return object;
            } else {
                long begin = System.currentTimeMillis();
                TimeUnit.MILLISECONDS.sleep(100);
                fix += System.currentTimeMillis() - begin;
            }

        }

        return object;
    }

    @Override
    public T poll() {
        T temp = super.poll();
        return temp;
    }

//    @Override
//    public T pollFirst() {
//        return poll();
//    }

//    @Override
//    public T pollFirst(long timeout, TimeUnit unit) throws InterruptedException {
//        return poll(timeout, unit);
//    }
//
//    @Override
//    public T pollLast() {
//        throw new UnsupportedOperationException("pollLast Unsupported now");
//    }
//
//    @Override
//    public T pollLast(long timeout, TimeUnit unit) throws InterruptedException {
//        throw new UnsupportedOperationException("takeLast Unsupported now");
//    }
//
//    @Override
//    public T pop() {
//
//        return super.pop();
//    }

//    @Override
//    public void push(T bytes) {
//        throw new UnsupportedOperationException("push Unsupported now");
//    }

    @Override
    public void put(T bytes) throws InterruptedException {
        while (!offer(bytes)) {
            TimeUnit.MILLISECONDS.sleep(100);
        }
    }

//    @Override
//    public void putFirst(T bytes) throws InterruptedException {
//        throw new UnsupportedOperationException("putFirst Unsupported now");
//    }

//    @Override
//    public void putLast(T bytes) throws InterruptedException {
//        while (!offerLast(bytes)) {
//            TimeUnit.MILLISECONDS.sleep(100);
//        }
//
//    }

    @Override
    public int remainingCapacity() {
        throw new UnsupportedOperationException("remainingCapacity Unsupported now");
    }

//    @Override
//    public T removeFirst() {
//        return poll();
//    }
//
//    @Override
//    public boolean removeFirstOccurrence(Object o) {
//        throw new UnsupportedOperationException("removeFirstOccurrence Unsupported now");
//    }

//    @Override
//    public T removeLast() {
//        throw new UnsupportedOperationException("removeLast Unsupported now");
//    }
//
//    @Override
//    public boolean removeLastOccurrence(Object o) {
//        throw new UnsupportedOperationException("removeLastOccurrence Unsupported now");
//    }

    @Override
    public T take() throws InterruptedException {
        T object;
        while ((object = this.poll()) == null) {
            TimeUnit.MILLISECONDS.sleep(100);
        }
        return object;
    }

//    @Override
//    public T takeFirst() throws InterruptedException {
//        return take();
//    }
//
//    @Override
//    public T takeLast() throws InterruptedException {
//        throw new UnsupportedOperationException("takeLast Unsupported now");
//    }

}
